A systematic review of positive interactions and the niche in deserts.
The niche is a powerful concept in ecology and at times not entirely coupled to local interactions between species. Herein, we review the capacity for these positive plant interactions to expand the niche of subdominant species. We synthesized the available literature using a formalized systematic review by using the Web of Science and associated terms with niche, positive interactions in plants such as facilitation, and deserts.
library(tidyverse)
library(DT)
#Search terms####
search.terms <- read_csv("data/search.terms.csv")
datatable(search.terms)
total.lit <- search.terms %>% filter(search != "final")
total.lit
## # A tibble: 6 x 4
## search terms hits hits.2017
## <chr> <chr> <int> <int>
## 1 1 plant facilitat* niche* arid* 47 50
## 2 2 plant facilitat* niche* desert* 32 31
## 3 3 nurse plant* niche* arid 16 19
## 4 4 nurse plant* niche* desert 11 11
## 5 5 positive interact* niche* desert* 21 21
## 6 6 positive interact* niche* arid* 29 35
totals <- sum(total.lit$hits)
totals
## [1] 156
final.list <- 53
totals-final.list
## [1] 103
#PRISMA####
#use 'prisma' function from PRISMAstatement
#https://cran.r-project.org/web/packages/PRISMAstatement/vignettes/PRISMA.html
prisma.report <-read_csv("data/prisma.csv")
prisma.report
## # A tibble: 53 x 4
## ID inclusion category
## <int> <chr> <chr>
## 1 1 N no positive interactions recorded
## 2 2 Y include
## 3 3 Y include
## 4 4 N no niche expansion recorded
## 5 5 Y include
## 6 6 N no positive interactions recorded
## 7 7 N no positive interactions recorded
## 8 8 N no positive interactions recorded
## 9 9 Y include
## 10 10 Y include
## # ... with 43 more rows, and 1 more variables: detailed.reason <chr>
exclusions <- prisma.report %>% filter(inclusion == "N") %>% select(ID, category)
dim(exclusions)
## [1] 24 2
library(PRISMAstatement)
#first search (2015)
prisma(found = 156,
found_other = 0,
no_dupes = 53,
screened = 53,
screen_exclusions = 0,
full_text = 53,
full_text_exclusions = 24,
qualitative = 0,
quantitative = 29,
width = 800, height = 800)
#second search (2017)
prisma(found = 196,
found_other = 0,
no_dupes = 70,
screened = 70,
screen_exclusions = 0,
full_text = 70,
full_text_exclusions = 34,
qualitative = 0,
quantitative = 36,
width = 800, height = 800)
#Summary of exclusions
categories <- exclusions %>% group_by(category) %>% tally() %>% arrange(desc(n))
categories
## # A tibble: 6 x 2
## category n
## <chr> <int>
## 1 no nurse plant 9
## 2 no positive interactions recorded 9
## 3 no niche expansion recorded 2
## 4 review 2
## 5 language 1
## 6 not desert 1
ggplot(categories, aes(category, n)) + geom_bar(stat = "identity") + coord_flip() + ylim(0,10)
search.1.1 <- read_csv("data/2016-search-total.csv")
search.1.2 <- read_csv("data/2017-search.csv")
net.difference <- anti_join(search.1.2, search.1.1, by = "DOI")
#net.difference <- net.difference %>% select(Title, DOI) #to simplify for a look
nrow(net.difference) #count of number of differences from consecutive search
## [1] 30
#write_csv(net.difference, "data/net.difference.csv")
#double-check
net.difference <- anti_join(search.1.2, search.1.1, by = "Title")
nrow(net.difference)
## [1] 59
data <- read_csv("data/data.csv")
data
## # A tibble: 36 x 17
## ID topic
## <int> <chr>
## 1 2 Niche characterization
## 2 3 Niche characterization
## 3 5 Niche partioning and interactions
## 4 9 Niche changes over ontogeny and inter-specific facilitation
## 5 10 Environmental niche: shade and rainfall of four shrubs
## 6 11 Coexistence in grass-shrub steppes
## 7 15 Niche differentiation/segregation in a shrubland
## 8 16 Niche partioning in tree-grass interactions
## 9 20 Niche partioning among shrub-annuals and biological crusts
## 10 21 Regeneration niche of six shrubs using one-week-old seedlings
## # ... with 26 more rows, and 15 more variables: expansion.mechanism <chr>,
## # niche.concept <chr>, application <chr>, niche.measurement <chr>,
## # benefactor <chr>, benefactor.life.form <chr>, benefactor.family <chr>,
## # beneficiary <chr>, beneficiary.life.form <chr>,
## # beneficiary.family <chr>, ecosystem <chr>, lat <dbl>, long <dbl>,
## # country <chr>, elevation.m <int>
#map####
#ggplot2 vers
require(maps)
world<-map_data("world")
map<-ggplot() + geom_polygon(data=world, fill="gray50", aes(x=long, y=lat, group=group))
map + geom_point(data=data, aes(x=long, y=lat)) + labs(x = "longitude", y = "latitude")
#data viz
data.simple <- data %>% group_by(niche.concept, ecosystem) %>% count()
ggplot(na.omit(data.simple), aes(niche.concept, n)) + geom_bar(stat = "identity") + coord_flip() + scale_fill_brewer(palette = "Blues") + labs(x = "niche concept", y =" frequency")
ggplot(na.omit(data.simple), aes(niche.concept, n, fill = ecosystem)) + geom_bar(stat = "identity") + coord_flip() + scale_fill_brewer(palette = "Blues") + labs(x = "niche concept", y =" frequency")
#too many levels
library(stringr)
data <- data %>%
rowwise() %>%
mutate(matches = str_replace(ecosystem,"^semi-arid.+", "semi-arid"))
data <- data %>%
rowwise() %>%
mutate(ecosystem = str_replace(ecosystem,"^semi-arid.+", "semi-arid")) %>%
mutate(ecosystem = str_replace(ecosystem,"^arid.+", "arid")) %>%
mutate(ecosystem = str_replace(ecosystem,"^open.+", "other")) %>%
mutate(ecosystem = str_replace(ecosystem,"^woodland.+", "other")) %>%
mutate(ecosystem = str_replace(ecosystem,"^sub.+", "other"))
#can also do ifelse() or use replace from dyplr
data.simple <- data %>% group_by(niche.concept, ecosystem) %>% count()
ggplot(na.omit(data.simple), aes(niche.concept, n, fill = ecosystem)) + geom_bar(stat = "identity") + coord_flip() + scale_fill_brewer(palette = "Blues") + labs(x = "niche concept", y =" frequency")
#now, do we need stats? if more >= 5
36/5 #yes
## [1] 7.2
c1<-chisq.test(data.simple$niche.concept, data.simple$n, simulate.p.value = TRUE, B = 10000)
c1 #n.s.
##
## Pearson's Chi-squared test with simulated p-value (based on 10000
## replicates)
##
## data: data.simple$niche.concept and data.simple$n
## X-squared = 20.75, df = NA, p-value = 0.5893
c1<-chisq.test(data.simple$ecosystem, data.simple$n, simulate.p.value = TRUE, B = 10000)
c1 #n.s.
##
## Pearson's Chi-squared test with simulated p-value (based on 10000
## replicates)
##
## data: data.simple$ecosystem and data.simple$n
## X-squared = 7.0583, df = NA, p-value = 0.9691
#count up levels for summary in results
n_distinct(data$country)
## [1] 11
n_distinct(data$niche.concept)
## [1] 5
n_distinct(data$ecosystem)
## [1] 4
The variation in methods, measrues, and reporting was to variable between and within studies within each major class of niche hypothesis. Hence, p-values with sample size estimates were extracted in all available instances.
Decision rules for selecting p-values
1. A p-value listed for the relevant process associated with the niche. For instance, there can be multiple measures tested and p-values reported. In this instance, extract the p-value most directly associated with the major niche concept. If there were different sections within results, the section entitle niche was inspect in most detail.
2. Record n for total number of fully independent samples. For instance, the number of individual plants was sometimes listed as 1000 but there were only 8 plots. Record n.reps as 8.
3. The number of species is the number of species directly tested associated with the niche hypothesis only.
4. If multiple responses were recorded and all were relevant to the niche hypothesis, select the p-max and/or measure that the authors interpreted as support for the mechanism.
#data from within each study
data <- read_csv("data/evidence.csv")
data <- data[!is.na(data$p), ]
#libary to use p-values for meta-analytic stats
library(metap)
schweder(data$p) # to explore validity of p-values to capture sense of whether it is a set of relatively small or large p-values as different combining probability tests have different assumptions.
sumz(p, data = data) #sumz assumes equal emphasis of large and small p-values
## sumz = 6.912241 p = 2.385276e-12
sumz(p, weights = n.reps, data = data) #weight by sample sizes
## sumz = 5.760639 p = 4.189799e-09
#then repeat for each hypothesis/niche.concept separately once all p-values collected
#sumz(p[niche.concept], data = data)
#sumz(data$p[niche.concept])
sumlog(data$p) #emphasis on small p-values and also known as Fisher’s method (most common combining probabitlities method) good general check
## chisq = 74.5954 with df = 12 p = 4.381382e-11